#ifndef __MY_HOT__
#define __MY_HOT__
#include <unistd.h>
#include "data.hpp"
#include "ThreadPool.hpp"

//热点管理模块: 对服务器上备份的文件进行检测，那些文件长时间没有被访问，则认为是非热点文件，则进行压缩存放到压缩路径，删除源文件，节省磁盘空间
//实现思路: 遍历所有的文件，检测文件最后一次访问时间，与当前时间进行相减得到差值，这个差值如果大于设定好的非热点判断时间，则对该文件进行热点处理 	

//遍历所有文件
//1.从数据管理模块中遍历所有备份文件信息 特殊情况：如果你在获取所有备份文件信息时，正好来了一个新文件信息，那我们就会漏掉一个
//2.遍历备份文件夹，获取所有的文件进行属性获取，最终判断
//使用第二种方式: 遍历文件夹，每次获取文件的最新数据进行判断，并且还可以解决数据信息缺漏的问题

//热点管理流程
//1.遍历备份目录 获取所有文件路径名称 
//2.逐个文件获取最后一次访问时间与当前系统时间进行比较判断，判断文件是否是非热点文件
//3.对非热点文件进行压缩处理，删除源文件
//4.修改数据管理模块对应的文件信息（压缩标志->true）
extern cloud::DataManager *_data;

namespace cloud{ 
	class HotManager{
		private:
			std::string _back_dir; //备份文件路径，因为我们需要获取备份文件信息
			std::string _pack_dir; //压缩文件路径，因为文件压缩之后我们需要将压缩文件存放到压缩路径下
			std::string _pack_suffix; //压缩包后缀名
			int _hot_time; //设定的热点时间

			ThreadPool* TP; //线程池

		private:
			//判断是否为热点文件，非热点文件-返回真；热点文件-返回假
			bool HotJudge(const std::string &filename){ 
				FileUtil fu(filename);
				time_t last_atime = fu.LastATime(); //文件最后一次访问时间
				time_t cur_time = time(NULL); //当前系统时间
				if (cur_time - last_atime > _hot_time){ //当前系统时间减去最后一次访问时间 > 设定热点时间 判断是否为热点文件 
					return true;
				}
				return false;
			} 
		public:
			HotManager() {
				Config *config = Config::GetInstance();
				_back_dir = config->GetBackDir();
				_pack_dir = config->GetPackDir();
				_pack_suffix = config->GetPackFileSuffix();
				_hot_time = config->GetHotTime();
				FileUtil tmp1(_back_dir);
				FileUtil tmp2(_pack_dir);
				tmp1.CreateDirectory();
				tmp2.CreateDirectory();

				TP = new ThreadPool;
			}

			void CompressTask(const std::string filename)
			{
				//3. 获取文件的备份信息
				BackupInfo bi; 
				//判断文件是否有备份信息，文件存在但是在_table中没有对应的映射关系
				//因为我们使用的真实路径，所以文件是绝对有的
				if (_data->GetOneByRealPath(filename, &bi) == false){//现在有一个文件存在，但是没有备份信息，漏存信息了
					bi.NewBackupInfo(filename);//设置一个新的备份信息出来
				}
				//3. 对非热点文件进行压缩处理
				FileUtil tmp(filename);
				tmp.Compress(bi.pack_path);
				//4. 删除源文件，修改备份信息
				tmp.Remove(); //删除源文件
				bi.pack_flag = true; //修改标记位为已压缩
				_data->Update(bi); //将该文件信息进行更新
			}

			bool RunModule() {
				while(1){ //一直进行处理, 判断是否有非热点文件
					//1. 遍历备份目录，获取所有文件名
					FileUtil fu(_back_dir);
					std::vector<std::string> arry;
	 				fu.ScanDirectory(&arry); //浏览目录获取所有文件名称
					//2. 遍历判断文件是否是非热点文件
					for (auto &a : arry) {
						if (HotJudge(a) == false){
							continue;//热点文件则不需要特别处理
						}
						
						//将压缩任务放到线程池中 bind的特性 返回一个函数对象由于CompressTask只有一个参数，还被我们绑定了，所以void()可以接收
						TP->enqueue(std::bind(&HotManager::CompressTask, this, a));
					}
					
					//定期清理非热点文件
					_data->CleanMemNonHot();
					usleep(1000);//避免目录中没有文件一直高速的循环遍历，导致占用cpu资源过高
				}
				return true;
			}


			// bool RunModule() {
			// 	while(1){ //一直进行处理, 判断是否有非热点文件
			// 		//1. 遍历备份目录，获取所有文件名
			// 		FileUtil fu(_back_dir);
			// 		std::vector<std::string> arry;
	 		// 		fu.ScanDirectory(&arry); //浏览目录获取所有文件名称
			// 		//2. 遍历判断文件是否是非热点文件
			// 		for (auto &a : arry) {
			// 			if (HotJudge(a) == false){
			// 				continue;//热点文件则不需要特别处理
			// 			}
			// 			//3. 获取文件的备份信息
			// 			BackupInfo bi; 
			// 			//判断文件是否有备份信息，文件存在但是在_table中没有对应的映射关系
			// 			//因为我们使用的真实路径，所以文件是绝对有的
			// 			if (_data->GetOneByRealPath(a, &bi) == false){//现在有一个文件存在，但是没有备份信息，漏存信息了
			// 				bi.NewBackupInfo(a);//设置一个新的备份信息出来
			// 			}
			// 			//3. 对非热点文件进行压缩处理
			// 			FileUtil tmp(a);
			// 			tmp.Compress(bi.pack_path);
			// 			//4. 删除源文件，修改备份信息
			// 			tmp.Remove(); //删除源文件
			// 			bi.pack_flag = true; //修改标记位为已压缩
			// 			_data->Update(bi); //将该文件信息进行更新
			// 		}
			// 		usleep(1000);//避免目录中没有文件一直高速的循环遍历，导致占用cpu资源过高
			// 	}
			// 	return true;
			//}
	};
}

#endif
